package com.example.sso.sso_server;

import cn.dev33.satoken.context.SaHolder;
import cn.dev33.satoken.sso.processor.SaSsoServerProcessor;
import cn.dev33.satoken.sso.template.SaSsoServerTemplate;
import cn.dev33.satoken.stp.StpUtil;
import cn.dev33.satoken.util.SaResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.ModelAndView;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

/**
 * Sa-Token-SSO Server端 Controller 
 */
@Slf4j
@RestController
public class SsoServerController {

    /**
     * SSO-Server端：处理所有SSO相关请求 
     * http://{host}:{port}/sso/auth            -- 单点登录授权地址
     * http://{host}:{port}/sso/doLogin        -- 账号密码登录接口，接受参数：name、pwd
     * http://{host}:{port}/sso/signout        -- 单点注销地址（isSlo=true时打开）
     */
    /** 聚合式路由，可修改为拆分式路由 */
    // @RequestMapping("/sso/*")
    public Object ssoRequest(HttpServletRequest request) {

        log.info("接口已接收到请求，" + request.getRequestURI());
        Object res = SaSsoServerProcessor.instance.dister();
        log.info("接口返回结果:{}", res);
        return res;
        
    }

    // SSO-Server：统一认证地址 
    @RequestMapping("/sso/auth")
    public Object ssoAuth() {
        log.info("/sso/auth接收到请求");
        return SaSsoServerProcessor.instance.ssoAuth();
    }

    // SSO-Server：RestAPI 登录接口 
    @RequestMapping("/sso/doLogin")
    public Object ssoDoLogin() {
        return SaSsoServerProcessor.instance.ssoDoLogin();
    }

    // SSO-Server：接收推送消息地址
    @RequestMapping("/sso/pushS")
    public Object ssoPushS() {
        return SaSsoServerProcessor.instance.ssoPushS();
    }

    // SSO-Server：单点注销 
    @RequestMapping("/sso/signout")
    public Object ssoSignout() {
        return SaSsoServerProcessor.instance.ssoSignout();
    }

    // 完全自定义一个接口来接受前端登录请求？
    // 直接定义一个拦截路由为 `/sso/doLogin` 的接口即可 
    // @RequestMapping("/sso/doLogin")
    public SaResult ss(String name, String pwd) {
        System.out.println("------ 请求进入了自定义的API接口 ---------- ");
        if("2479544118".equals(name) && "whxsdtc.1".equals(pwd)) {
            StpUtil.login(10001);
            return SaResult.ok("登录成功！");
        }
        return SaResult.error("登录失败！");
    }
    
    /**
     * 配置SSO相关参数 登陆处理等
     */
    @Autowired
    private void configSso(SaSsoServerTemplate ssoServerTemplate) {

        // 自定义API地址
        SaSsoServerProcessor.instance.ssoServerTemplate.apiName.ssoAuth = "/sso/auth2";
        
        // 配置：未登录时返回的View 
        ssoServerTemplate.strategy.notLoginView = () -> {
            // 简化模拟表单
            /*String doLoginCode =
                    "fetch(`/sso/doLogin?name=${document.querySelector('#name').value}&pwd=${document.querySelector('#pwd').value}`) " +
                            " .then(res => res.json()) " +
                            " .then(res => { if(res.code === 200) { location.reload() } else { alert(res.msg) } } )";
            String res =
                    "<h2>当前客户端在 SSO-Server 认证中心尚未登录，请先登录</h2>" +
                            "用户：<input id='name' /> <br> " +
                            "密码：<input id='pwd' /> <br>" +
                            "<button onclick=\"" + doLoginCode + "\">登录</button>";
            return res;*/

            return new ModelAndView("sa-login.html");
            
        };

        // 配置：登录处理函数 
        ssoServerTemplate.strategy.doLoginHandle = (name, pwd) -> {
            // 此处仅做模拟登录，真实环境应该查询数据库进行登录 
            SaResult saResult;
            if("2479544118".equals(name) && "whxsdtc.1".equals(pwd)) {
                StpUtil.login(10001);
                saResult = SaResult.ok("登录成功！").setData(StpUtil.getTokenValue());
            }else {
                saResult = SaResult.error("登录失败！");
            }

            // 在任意代码处获取前端提交的参数 
            String xxx = SaHolder.getRequest().getParam("xxx");

            return saResult;
        };

        // 添加消息处理器：userinfo (获取用户资料) （用于为 client 端开放拉取数据的接口）
        ssoServerTemplate.messageHolder.addHandle("userinfo", (ssoTemplate, message) -> {
            System.out.println("收到消息：" + message);

            // 自定义返回结果（模拟）
            return SaResult.ok()
                    .set("id", message.get("loginId"))
                    .set("name", "LinXiaoYu")
                    .set("sex", "女")
                    .set("age", 18);
        });
    }

}

